package dao

import (
    "errors"
    "user_srv/basic/config"
    "user_srv/handler/models"
)

// ListInterests 查询全部可用兴趣项。
//
// 行为与约定：
// - 从表 `interest` 读取所有记录，按 `sort ASC, id ASC` 排序；
// - 仅做只读查询，不包含任何写操作；
//
// 返回值：
// - ([]models.Interest, nil): 查询成功且可能为长度为 0 的切片；
// - (nil, error): 底层数据库查询失败时返回错误（带有中文上下文前缀便于排查）。
//
// 复杂度：O(n)，n 为兴趣项总数。
func ListInterests() ([]models.Interest, error) {
    var list []models.Interest
    if err := config.DB.Order("sort asc, id asc").Find(&list).Error; err != nil {
        return nil, errors.New("查询兴趣失败" + err.Error())
    }
    return list, nil
}

// SetUserInterests 为指定用户批量设置兴趣绑定关系（强制最多 10 项）。
//
// 入参：
// - userId: 目标用户 ID，必须为非 0 值；
// - interestIds: 兴趣 ID 列表，函数内部会强制截断到前 10 个元素；
//
// 事务语义：
// - BEGIN 事务；
//   1) 删除该用户在 `user_interest` 的所有旧记录；
//   2) 逐个插入新的 (user_id, interest_id) 记录；
// - 全部成功则 COMMIT；任一步失败则 ROLLBACK 并返回错误；
//
// 错误返回：
// - 清空旧绑定失败：返回带中文前缀的错误信息；
// - 插入任一新绑定失败：回滚并返回错误；
// - Commit 失败：返回底层提交错误；
//
// 幂等性：
// - 在相同的 interestIds 输入下，重复调用将产生相同的最终绑定集合；
//
// 并发性：
// - 在高并发对同一 userId 频繁写入的场景下，最后一次提交事务的结果为准；
//   如需更强的一致性，可考虑显式加锁或引入版本号机制。
func SetUserInterests(userId uint64, interestIds []uint64) error {
    if len(interestIds) > 10 {
        interestIds = interestIds[:10]
    }
    tx := config.DB.Begin()
    if err := tx.Where("user_id = ?", userId).Delete(&models.UserInterest{}).Error; err != nil {
        tx.Rollback()
        return errors.New("清空旧兴趣失败" + err.Error())
    }
    for _, iid := range interestIds {
        // 默认写入展示状态 status=1
        if err := tx.Create(&models.UserInterest{UserId: userId, InterestId: iid, Status: 1}).Error; err != nil {
            tx.Rollback()
            return errors.New("保存兴趣失败" + err.Error())
        }
    }
    return tx.Commit().Error
}

// GetUserInterests 查询用户已选择的兴趣详细信息。
//
// 行为与约定：
// - 通过 `user_interest` 关联 `interest` 表，返回该用户选择的兴趣集合；
// - 字段包含 id、name、sort，并按 `sort ASC, id ASC` 排序；
//
// 返回值：
// - ([]models.Interest, nil): 查询成功（可能为空切片表示尚未选择）；
// - (nil, error): 底层查询失败；
//
// 复杂度：
// - O(k)，k 为用户已选择兴趣的数量。
func GetUserInterests(userId uint64) ([]models.Interest, error) {
    var interests []models.Interest
    err := config.DB.Table(models.UserInterest{}.TableName()+" ui").
        Select("i.id, i.name, i.sort").
        Joins("join "+models.Interest{}.TableName()+" i on ui.interest_id = i.id").
        Where("ui.user_id = ? AND ui.status = 1", userId).
        Order("i.sort asc, i.id asc").
        Scan(&interests).Error
    if err != nil {
        return nil, errors.New("查询用户兴趣失败" + err.Error())
    }
    return interests, nil
}


